package im.frape.model;

import im.frape.ContactList;
import im.frape.R;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jivesoftware.smack.XMPPConnection;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.util.Log;
import android.widget.ArrayAdapter;

public class FrapeModel extends Handler {
	private static final String TAG = "FrapeModel";
	private static FrapeModel instance;
	private ContactList contactList;
	private SharedPreferences preferences;
	private Map<String, JabberAccount> accounts;
	// private List<JabberContact> contacts;
	private Context context;
	private ArrayAdapter<String> adapter;
	private ArrayList<String> array;
	private FrapeRoster frapeRoster;

	/* Keys used for storing/retrieving values */
	/*private static final String KEY_JABBERIDS = "jabberids";
	private static final String KEY_PASSWORDS = "passwords";
	private static final String KEY_SERVERS = "servers";
	private static final String KEY_PORTS = "ports";
	private static final String KEY_RESOURCES = "resources";
	private static final String KEY_ENCRYPTIONS = "encryptions";
	private static final String KEY_AUTOLOGINS = "autologins";
	private static final String DELIMITER = ";";
	*/

	public static FrapeModel getInstance() {
		if (instance == null) {
			instance = new FrapeModel();
		}
		return instance;
	}

	public void initialize(SharedPreferences preferences, Context context) {
		Log.i(TAG, "Initialization");
		this.preferences = preferences;
		this.context = context;
		this.accounts = initAccounts();
		// this.contacts = initContacts();
		this.contactList = ContactList.getInstance();
		this.array = new ArrayList<String>();
		this.adapter = new ArrayAdapter<String>(this.contactList, R.layout.account_item, this.array);
		this.frapeRoster = FrapeRoster.getInstance();

	}

	private List<JabberContact> initContacts() {
		// TODO Auto-generated method stub
		List<JabberContact> contacts = new ArrayList<JabberContact>();
		return contacts;
	}

	private Map<String, JabberAccount> initAccounts() {
		Log.i(TAG, "Doing initAccoints()");
		Map<String, JabberAccount> accounts = new HashMap<String, JabberAccount>();
		try {
			String[] files = context.fileList();
			for (String soubor : files) {
				Log.i(TAG, "Listed file: " + soubor);
			}
			/* Fetch the information */
			/*
			 * / String jabberids = prefs.getString(KEY_JABBERIDS, ""); String
			 * passwords = prefs.getString(KEY_PASSWORDS, ""); String servers =
			 * prefs.getString(KEY_SERVERS, ""); String[] jabberidsSplited =
			 * jabberids.split(DELIMITER); String[] passwordsSplited =
			 * passwords.split(DELIMITER); String[] serversSplited =
			 * servers.split(DELIMITER);
			 * 
			 * for (int i = 0; i < jabberidsSplited.length; i++) {
			 * accounts.add(new JabberAccount(jabberidsSplited[i],
			 * passwordsSplited[i], serversSplited[i], 0, "", false, false)); }
			 * 
			 * /
			 */
			// TODO test data
			// accounts.add(new JabberAccount("pokusnej_kralik@jabbim.cz",
			// "123456",
			// "jabbim.cz"));
			// accounts.add(new JabberAccount("frape", "123456",
			// "jabber.segfault.cz"));
			/**/
			for (String file : files) {
				try {
					FileInputStream fis = context.openFileInput(file);
					ObjectInputStream ois = new ObjectInputStream(fis);
					JabberAccount ac = (JabberAccount) ois.readObject();
					accounts.put(ac.getJabberId(), ac);
					ois.close();
					fis.close();
				} catch (FileNotFoundException ex) {
					// TODO Auto-generated catch block
					Log.i(TAG, ex.getMessage());
				} catch (StreamCorruptedException ex) {
					// TODO Auto-generated catch block
					Log.i(TAG, ex.getMessage());
				} catch (IOException ex) {
					// TODO Auto-generated catch block
					Log.i(TAG, ex.getMessage());
				} catch (ClassNotFoundException ex) {
					// TODO Auto-generated catch block
					Log.i(TAG, ex.getMessage());
				}
			}
		} catch (NullPointerException ex) {
			ex.printStackTrace();
			return accounts;
		}
		return accounts;
	}

	/*
	public void saveAccounts() {
		//Save some new information 
		
		  SharedPreferences.Editor editor = prefs.edit();
		  editor.putString(KEY_JABBERIDS, jabberids);
		  editor.putString(KEY_PASSWORDS, passwords);
		  editor.putString(KEY_SERVERS, servers); editor.commit();
		 	}
	 */

	public JabberAccount[] getAccounts() {
		return accounts.values().toArray(new JabberAccount[accounts.values().size()]);
	}

	public void addAccount(JabberAccount account) {
		accounts.put(account.getJabberId(), account);
		String FILENAME = "account_" + account.getJabberId();
		try {
			FileOutputStream fos = context.openFileOutput(FILENAME, context.MODE_PRIVATE);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(account);
			oos.close();
			fos.close();
			Log.i(TAG, "File " + FILENAME + " has been written.");
		} catch (FileNotFoundException ex) {
			// TODO Auto-generated catch block
			ex.printStackTrace();
		} catch (IOException ex) {
			// TODO Auto-generated catch block
			ex.printStackTrace();
		}
	}

	public void reconnectWithContactList() {
		this.contactList = ContactList.getInstance();
		this.adapter = new ArrayAdapter<String>(this.contactList, R.layout.account_item, this.array);
		this.adapter.notifyDataSetChanged();
	}

	public void addAccountRoster(JabberAccount account) {
		this.frapeRoster.addRoster(account.getJabberId(), account.getRoster());
		Log.i(TAG, "Add all from roster");
		this.array.clear();
		// this.frapeRoster.rosters.get(account.getJabberId()).reload();
		for (String string : this.frapeRoster.getAllUsers()) {
			Log.i(TAG, string);
			try {
				this.adapter.add(string);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		// this.adapter.addAll(this.frapeRoster.getAllUsers());
		// this.adapter.notifyDataSetChanged();
		for (String neco : array) {
			Log.i(TAG, neco);
		}
		Log.i(TAG, "Add all from roster done");
	}

	public void removeAccountRoster(JabberAccount account) {
		Log.i(TAG, "Removing account roster for " + account.getJabberId());
		this.frapeRoster.removeRoster(account.getJabberId());
		this.array.clear();
		this.adapter.clear();
		this.adapter.notifyDataSetChanged();
		this.contactList.invalidateContactsListView();
		for (String string : this.frapeRoster.getAllUsers()) {
			Log.i(TAG, string);
			try {
				this.adapter.add(string);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		Log.i(TAG, "Removed account roster");
	}

	/*
	private void refreshContacts() {
		Log.i(TAG, "Refreshing contacts");
		for (JabberAccount account : accounts) {
			if (!account.isEnabled()) {
				for (JabberContact contact : contacts) {
					if (contact.getAccount().equalsIgnoreCase(account.getJabberId())) {

						contacts.remove(contact);
						Log.i(TAG, "Removed contact " + contact.getJID());
					}
				}
			}
		}
	}*/
	/*
	public List<JabberContact> getContacts() {
		Log.i(TAG, "Geting Contacts");

		contacts.clear();
		for (JabberAccount account : this.accounts) {
			if (account.isConnected()) {
				Collection<RosterEntry> rosterEntryCol = frapeRoster.getRoster(account.getJabberId()).getEntries();
				for (RosterEntry re : rosterEntryCol) {
					Log.i(TAG, "Reading roster entry: " + re.getName());
					contacts.add(new JabberContact(re.getName(), re.getUser(), account.getJabberId()));
				}
			}
		}
		return contacts;
		// return this.frapeRoster.
	}*/

	public void removeAccount(JabberAccount account) {
		accounts.remove(account);
		context.deleteFile("account_" + account.getJabberId());
	}

	/*
	private void refreshContactArray() {
		Log.i(TAG, "Refreshing Array");
		this.adapter.setNotifyOnChange(false);
		array.clear();
		for (JabberContact contact : contacts) {
			array.add(contact.getJID());
		}
		this.adapter.notifyDataSetChanged();
	}
	*/

	/*
	public void addContact(JabberContact jabberContact) {
		contacts.add(jabberContact);
	}
	*/
	/*
		public void connectAccount(JabberAccount account) {
			// account.connect();
			// Log.i(TAG, "Trying to refresh contactlist");
			// getContacts();
		}

		public void disconnectAccount(JabberAccount account) {
			Roster roster = account.getRoster();
			Collection<RosterEntry> re = roster.getEntries();
			this.adapter.setNotifyOnChange(false);
			for (RosterEntry entry : re) {
				array.remove(entry.getUser());
			}
			this.adapter.notifyDataSetChanged();
			account.disconnect();
		}
	*/
	/*
	@Override
	public void entriesAdded(Collection<String> arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "Entries Adding");
		// contactsListView.setAdapter(new ArrayAdapter<String>(this,
		// R.layout.account_item, (String[]) arg0.toArray()));
		this.adapter.setNotifyOnChange(false);
		this.array = this.frapeRoster.getUsers();
		this.adapter.notifyDataSetChanged();
		Log.i(TAG, "Entries Adding ended");
	}

	@Override
	public void entriesDeleted(Collection<String> arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "Entries Deleted");
		this.adapter.setNotifyOnChange(false);
		for (String contact : arg0) {
			Log.i(TAG, "Removed " + contact);

		}
		this.adapter.notifyDataSetChanged();
	}

	@Override
	public void entriesUpdated(Collection<String> arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "Entries Updated");

		for (String contact : arg0) {
			Log.i(TAG, "Updated" + contact);
		}
		Log.i(TAG, "Entries Updated");
	}

	@Override
	public void presenceChanged(Presence arg0) {
		// TODO Auto-generated method stub
		Log.i(TAG, "Presence Changed");

	}
	*/
	public ArrayAdapter<String> getArrayAdapter() {
		return adapter;
	}

	/*
	 * public void refreshContactList() { // TODO Auto-generated method stub
	 * this.contactList.refreshContactsListView(); }
	 */
	public XMPPConnection getConnection(String JID) {
		return this.accounts.get(JID).getConnecton();
	}

}
